import * as cc from "cc";
import yyComponent from "../../Script/Common/yyComponent";
import { GlobalEnum } from "../../Script/GameSpecial/GlobalEnum";
import { EventType } from "../../Script/GameSpecial/GameEventType";
import Action3dManager, { ActionMngType, Action3d } from "../../Script/Common/Action3dManager";
import GlobalPool from "../../Script/Common/GlobalPool";
import GlobalData from "../../Script/Common/GlobalData";
import { MiniMap } from "./MiniMap";
import { RankLayer } from "./RankLayer";

//关卡进度分数等信息UI
const { ccclass, property } = cc._decorator;

@ccclass
export default class LevelInfoUI extends yyComponent {

    public get uiType() { return GlobalEnum.UI.levelInfo; }

    public init() {
        this.initCurGold();
        this.initDirIcon();
        this.initHandAnim();
        this.initProgress();
        this.initKillTip();
        this.initTeachTip();
        this.addSimpleComp(this.miniMap);
        this.addSimpleComp(this.rank);

        this.onEvents();
    }
    protected onEvents() {
        this.on(EventType.LevelEvent.resurgence, this.onResurgence, this);
        this.on(EventType.LevelEvent.updateRemainEnemy, this.updateRemainEnemy, this);
        this.on(EventType.LevelEvent.updateGold, this.updateGold, this);
        this.on(EventType.LevelEvent.enemyDead, this.removeDirIcon, this);
        this.on(EventType.LevelEvent.playerKillEnemy, this.showKillTip, this);
        this.on(EventType.Common.DirectorEvent.playerWin, this.hideGoldBar, this);
        this.on(EventType.LevelEvent.showHandAnim, this.showHandAnim, this);
        this.on(EventType.LevelEvent.decideWeaponSkin, this.showHandAnim, this);
        this.on(EventType.LevelEvent.showHandAnim, this.showProgress, this);
        this.on(EventType.LevelEvent.decideWeaponSkin, this.showTeachTip, this);
        this.once(EventType.LevelEvent.startJoy, this.hideHandAnim, this);
    }
    public reset() {
        this.resetCurGold();
        this.resetDirIcon();
        this.resetHandAnim();
        this.resetProgress();
        this.resetKillTip();
        this.resetTeachTip();
        this.resetSimpleComps();
    }

    public show(levelData: any) {
        this.node.active = true;
        this.reset();
        this.setData(levelData);
        this.onEvents();
        this.miniMap.show();
        this.rank.show();
        this.emit(EventType.Common.DirectorEvent.resumeLevel);
    }
    public hide() {
        this.reset();
        this.offEvents();
        this.node.active = false;
    }

    public getData() {
        return {
            lv: this.lv,
            speGold: 0,
            gold: 1,
            // gold: this.curGold,
        };
    }

    protected lv: number;
    protected setData(data: any) {
        this.lv = data.lv;
        let enemies = GlobalData.get(GlobalEnum.myGlobalDataType.matchEnemies);
        this.totalEnemyCount = enemies.length;
        this.remainCount.string = "" + this.totalEnemyCount;
        this.curLevel.string = "" + this.lv;
        this.nextLevel.string = "" + (this.lv + 1);
        this.levelProgress.width = 1;
    }

    protected convertToString(v: number): string {
        if (v < 1100) return v.toString();
        if (v < 1100000) return (v * 0.001).toFixed(1) + "K";
        return (v * 0.000001).toFixed(1) + "M";
    }

    /****************************************管理对象****************************************/
    //#region 关卡进度
    @property(cc.Node)
    protected levelProgressBg: cc.Node = null;
    @property(cc.UITransform)
    protected levelProgress: cc.UITransform = null;
    protected levelProgressTotalLength: number = 349;
    @property(cc.Label)
    protected curLevel: cc.Label = null;
    @property(cc.Label)
    protected nextLevel: cc.Label = null;
    @property(cc.Label)
    protected remainCount: cc.Label = null;
    protected totalEnemyCount: number = 10;
    protected initProgress() {
        this.levelProgressTotalLength = this.levelProgress.getComponent(cc.Sprite).spriteFrame.originalSize.width;
        this.levelProgress.width = this.levelProgressTotalLength;
        this.levelProgressBg.active = false;
    }
    protected resetProgress() {
        this.levelProgressBg.active = false;
    }
    protected updateRemainEnemy(c: number) {
        this.remainCount.string = "" + c;
        let w = this.levelProgressTotalLength * (1 - c / this.totalEnemyCount);
        if (w < 1) {
            w = 1;
        }
        this.levelProgress.width = w;
    }
    protected showProgress() {
        this.levelProgressBg.active = true;
    }
    //#endregion

    //#region 金币
    @property(cc.Label)
    protected curGoldLabel: cc.Label = null;
    protected curGold: number = 0;
    protected _goldTargetPos: cc.Vec3;
    protected goldAddElapsed: number = 0;
    protected goldAddDuration: number = 0.1;

    protected get goldTargetPos() {
        if (!this._goldTargetPos) {
            this._goldTargetPos = this.curGoldLabel.getComponent(cc.UITransform).convertToWorldSpaceAR(cc.v3());
            this.node.getComponent(cc.UITransform).convertToNodeSpaceAR(this._goldTargetPos, this._goldTargetPos);
        }
        return this._goldTargetPos;
    }
    protected initCurGold() {
        this.curGold = 0;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = this.goldAddDuration + 1;
    }
    protected resetCurGold() {
        this.curGold = 0;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = this.goldAddDuration + 1;
        this.curGoldLabel.node.parent.active = true;
    }
    protected addGold(v: number = 1) {
        this.curGold += v;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = 0;
    }
    protected hideGoldBar() {
        this.curGoldLabel.node.parent.active = false;
    }
    protected updateGold(g) {
        this.curGold = g;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = 0;
    }
    protected updateGoldLabel(dt: number) {
        if (this.goldAddElapsed > this.goldAddDuration) { return; }
        this.goldAddElapsed += dt;
        let r = 1 - this.goldAddElapsed / this.goldAddDuration;
        if (r < 0) r = 0;
        let s = 1 + 1 * r;
        this.curGoldLabel.node.setScale(s, s, s);
    }
    //#endregion

    //#region 金币动画层
    @property(cc.Node)
    protected goldParticleLayer: cc.Node = null;
    @property(cc.Prefab)
    protected goldParticle: cc.Prefab = null;
    protected initGoldParticleLayer() {
        GlobalPool.createPool(this.goldParticle.name, this.goldParticle);
    }
    protected resetGoldParticleLayer() {
        GlobalPool.putAllChildren(this.goldParticleLayer, true);
    }
    protected addGoldParticle(data: { p: cc.Vec3, gold: number }) {
        let node = GlobalPool.get(this.goldParticle.name);
        this.goldParticleLayer.addChild(node);
        let p = this.node.getComponent(cc.UITransform).convertToNodeSpaceAR(data.p);
        node.setPosition(p);
        let s = 1;
        node.setScale(s, s);
        let d = 1;
        let move = Action3dManager.moveTo(d, this.goldTargetPos.x, this.goldTargetPos.y, 0);
        move.easing(Action3dManager.easeIn(3));
        s = 0.5;
        let scale = Action3dManager.scaleTo(d, s, s, 1);
        scale.easing(Action3dManager.easeIn(2));
        let spawn = Action3dManager.spawn(move, scale);
        let cb = Action3dManager.callFun(this.onGoldParticleAnimFinish, this, { node: node, gold: data.gold });
        let seq = Action3dManager.sequence(spawn, cb);
        Action3dManager.getMng(ActionMngType.UI).runAction(node, seq);
    }
    protected onGoldParticleAnimFinish(data: { node: cc.Node, gold: number }) {
        this.addGold(data.gold);
        GlobalPool.put(data.node);
    }
    //#endregion

    //#region 敌人方向
    @property(cc.Node)
    protected dirIconLayer: cc.Node = null;
    @property(cc.Prefab)
    protected dirIconPrefab: cc.Prefab = null;
    protected dirIconName: string;
    protected dirIconMap: { [id: number]: cc.Node } = null;
    protected dirElapsed: number = 0;
    protected dirDuration: number = 0.01;
    protected dirPtr: number = 0;
    protected dirCachePos: cc.Vec3 = null;
    protected dirScope: cc.Vec2 = null;
    protected initDirIcon() {
        this.dirIconName = this.dirIconPrefab.data.name;
        GlobalPool.createPool(this.dirIconName, this.dirIconPrefab, null);
        GlobalPool.preCreate(this.dirIconName, 10);
        this.dirIconMap = {};
        this.dirElapsed = 0;
        this.dirCachePos = cc.v3();
        let cvs: cc.UITransform = GlobalData.get(GlobalEnum.Common.GlobalDataType.canvasTransform);
        this.dirScope = cc.v2(cvs.width * 0.5 - 20, cvs.height * 0.5 - 20);
    }
    protected resetDirIcon() {
        GlobalPool.putAllChildren(this.dirIconLayer, true);
        this.dirIconMap = {};
        this.dirElapsed = 0;
        this.dirPtr = 0;
    }
    protected fillDirIcon(enemies) {
        if (this.dirIconLayer.children.length == 0) {
            for (let i = 0, c = enemies.length; i < c; ++i) {
                let node = GlobalPool.get(this.dirIconName);
                node.setPosition(-9999, -9999, 0);
                this.dirIconLayer.addChild(node);
                this.dirIconMap[enemies[i].Id] = node;
            }
        }
    }
    protected removeDirIcon(enemy) {
        let id = enemy.Id;
        if (!!this.dirIconMap[id]) {
            GlobalPool.put(this.dirIconMap[id]);
            delete this.dirIconMap[id];
        }
    }
    protected updateDirIcon(dt: number) {
        // this.dirElapsed += dt;
        // if (this.dirElapsed < this.dirDuration) {
        //     return;
        // }
        // this.dirElapsed = 0;

        let enemies = GlobalData.get(GlobalEnum.myGlobalDataType.enemies);
        if (!enemies || enemies.length == 0) {
            this.resetDirIcon();
            return;
        }
        this.fillDirIcon(enemies);
        // if (++this.dirPtr >= enemies.length) {
        //     this.dirPtr = 0;
        // }
        for (let i = enemies.length - 1; i >= 0; --i) {
            this.updateOneDirIcon(enemies[i]);
        }
    }
    protected updateOneDirIcon(e) {
        this.dirCachePos.set(e.node.position);
        let camera: cc.CameraComponent = GlobalData.get(GlobalEnum.Common.GlobalDataType.levelCamera).camera;
        camera.convertToUINode(this.dirCachePos, this.dirIconLayer, this.dirCachePos);
        let active = false;
        let dir = 0;
        if (this.dirCachePos.x < -this.dirScope.x) {
            this.dirCachePos.y *= -this.dirScope.x / this.dirCachePos.x;
            this.dirCachePos.x = -this.dirScope.x;
            active = true;
            dir = 2;
        } else if (this.dirCachePos.x > this.dirScope.x) {
            this.dirCachePos.y *= this.dirScope.x / this.dirCachePos.x;
            this.dirCachePos.x = this.dirScope.x;
            active = true;
            dir = 0;
        }
        if (this.dirCachePos.y < -this.dirScope.y) {
            this.dirCachePos.x *= -this.dirScope.y / this.dirCachePos.y;
            this.dirCachePos.y = -this.dirScope.y;
            active = true;
            dir = 3;
        } else if (this.dirCachePos.y > this.dirScope.y) {
            this.dirCachePos.x *= this.dirScope.y / this.dirCachePos.y;
            this.dirCachePos.y = this.dirScope.y;
            active = true;
            dir = 1;
        }
        let node = this.dirIconMap[e.Id];
        node.active = active;
        if (active) {
            node.setPosition(this.dirCachePos);
            let radian = Math.atan2(this.dirCachePos.y, this.dirCachePos.x) + 1.57;
            radian *= 0.5;
            node.setRotation(0, 0, Math.sin(radian), Math.cos(radian));

            // let radian = dir * 1.57 + 1.57;
            // radian *= 0.5;
            // node.setRotation(0, 0, Math.sin(radian), Math.cos(radian));
        }
    }

    //#endregion

    //#region 击杀提示
    @property(cc.Node)
    protected killTipLayer: cc.Node = null;
    protected initKillTip() {
        for (let i = this.killTipLayer.children.length - 1; i >= 0; --i) {
            this.killTipLayer.children[i].setScale(0, 0, 0);
        }
    }
    protected resetKillTip() {
        let actMng = Action3dManager.getMng(ActionMngType.UI);
        for (let i = this.killTipLayer.children.length - 1; i >= 0; --i) {
            actMng.stopAllActions(this.killTipLayer.children[i]);
            this.killTipLayer.children[i].setScale(0, 0, 0);
        }
    }
    protected showKillTip() {
        let children = this.killTipLayer.children;
        let index = Math.floor(Math.random() * children.length - 0.001);
        for (let i = children.length - 1; i >= 0; --i) {
            if (children[i].scale.x > 0) {
                index++;
            }
        }
        if (index >= children.length) {
            index %= children.length;
        }
        let s = 0;
        let node = children[index];
        node.setScale(s, s, s);
        let d = 1.3;
        s = 1;
        let scale0 = Action3dManager.scaleTo(d, s, s, s);
        scale0.easing(Action3dManager.easeElasticOut(0.3));
        s = 0;
        let scale1 = Action3dManager.scaleTo(0, s, s, s);
        let seq = Action3dManager.sequence(scale0, scale1);
        Action3dManager.getMng(ActionMngType.UI).runAction(node, seq);
    }
    //#endregion

    // //#region 胜利动画
    // @property(WinAnim)
    // protected winAnim: WinAnim = null;
    // protected initWinAnim() {
    //     this.winAnim.init();
    //     this.winAnim.hide();
    // }
    // protected resetWinAnim() {
    //     this.winAnim.reset();
    //     this.winAnim.hide();
    // }
    // protected playWinAnim() {
    //     this.winAnim.play();
    // }
    // //#endregion

    // //#region 失败动画
    // @property(LoseAnim)
    // protected loseAnim: LoseAnim = null;
    // protected initLoseAnim() {
    //     this.loseAnim.init();
    //     this.loseAnim.hide();
    // }
    // protected resetLoseAnim() {
    //     this.loseAnim.reset();
    //     this.loseAnim.hide();
    // }
    // protected playLoseAnim() {
    //     this.loseAnim.play();
    // }
    // //#endregion

    //#region 手指提示动画
    @property(cc.Node)
    protected handLoop: cc.Node = null;
    @property(cc.Animation)
    protected handAnim: cc.Animation = null;
    protected initHandAnim() {
        this.hideHandAnim();
    }
    protected resetHandAnim() {
        this.hideHandAnim();
    }
    protected showHandAnim() {
        this.once(EventType.LevelEvent.startJoy, this.hideHandAnim, this);
        this.handLoop.active = true;
        this.handAnim.play();
    }
    protected hideHandAnim() {
        this.handAnim.stop();
        this.handLoop.active = false;
    }
    //#endregion

    //#region 教学文字提示
    @property(cc.Node)
    protected teachTip: cc.Node = null;
    protected teachTipAction: Action3d = null;
    protected initTeachTip() {
        this.teachTip.active = false;
        let fadeIn = Action3dManager.fadeTo(0, 255);
        let delay = Action3dManager.delay(8);
        let fadeOut = Action3dManager.fadeTo(1, 0);
        this.teachTipAction = Action3dManager.sequence(fadeIn, delay, fadeOut);
    }
    protected resetTeachTip() {
        Action3dManager.getMng(ActionMngType.Level).stopAllActions(this.teachTip);
        this.teachTip.active = false;
    }
    protected showTeachTip() {
        this.teachTip.active = true;
        Action3dManager.getMng(ActionMngType.Level).runAction(this.teachTip, this.teachTipAction);
    }
    //#endregion

    //#region 小地图
    @property(MiniMap)
    protected miniMap: MiniMap = null;
    //#endregion

    //#region 排行榜
    @property(RankLayer)
    protected rank: RankLayer = null;
    //#endregion


    /****************************************按钮回调****************************************/
    /**设置按钮 */
    protected onBtnConfigSetting() {
        this.emit(EventType.Common.AudioEvent.playClickBtn);
        this.emit(EventType.Common.UIEvent.enter, GlobalEnum.UI.configSetting);
    }
    /**暂停按钮 */
    protected onBtnPause() {
        this.emit(EventType.Common.AudioEvent.playClickBtn);
        this.emit(EventType.Common.UIEvent.enter, GlobalEnum.UI.pauseLevel);
    }


    //测试用：返回首页
    protected onBtnLobby() {
        this.emit(EventType.Common.DirectorEvent.enterLobby);
    }

    protected onBtnWin() {
        this.emit(EventType.LevelEvent.testWin);
    }
    protected onBtnLose() {
        this.emit(EventType.LevelEvent.testLose);
    }

    protected onResurgence() {
        // this.resetLoseAnim();
    }

    public update(dt: number) {
        this.updateGoldLabel(dt);
        this.updateDirIcon(dt);
    }

}
